package com.ldg.seckill.utils;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ld.utils.MyDate;
import com.ldg.seckill.entity.TbSeckillGoods;
import com.ldg.seckill.service.TbSeckillGoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @Author: Liudao
 * @Date: 2022-10-21-17:11
 * @Description:
 */
@Component
@EnableScheduling
public class SchedulingTask {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private TbSeckillGoodsService goodsService;

//    @Scheduled(cron = "* * * * * ?")
//    public void hello(){
//        System.out.println("Now:" + new Date().toString());
//    }

    @Scheduled(cron = "0/30 * * * * ?")
    public void SchedulingSelectSeckillGoods(){
        //得到12个时间段
        List<Date> dateMenus = MyDate.getDateMenus();
        //遍历
        for (Date dateMenu : dateMenus) {
            //构造查询条件对象
            QueryWrapper<TbSeckillGoods> wrapper = new QueryWrapper<>();
            //秒杀商品开始时间大于等于某个时间段的开始
            wrapper.ge("start_time",dateMenu);
            //秒杀商品结束时间小于等于某个时间段的结束
            wrapper.le("end_time",MyDate.addDateHour(dateMenu,2));
            //秒杀商品是审核通过的
            wrapper.eq("status",1);
            //商品的库存应大于0
            wrapper.gt("stock_count",0);
            //如果商品在redis中不存在，组合商品在redis中存储的keys
            Set<Object> keys = redisTemplate.boundHashOps("seckillGoods_" + MyDate.getDateStr(dateMenu)).keys();
            //如果keys存在，把没在redis中的商品找到
            if (keys != null && keys.size()>0){
                wrapper.notIn("id",keys);
            }
            //查找秒杀商品
            List<TbSeckillGoods> goods = goodsService.findGoodsList(wrapper);
            //把商品放到redis（放之前进行处理）
            for (TbSeckillGoods good : goods) {
                BoundHashOperations<String, String, String> ops = redisTemplate.boundHashOps("seckillGoods_" + MyDate.getDateStr(dateMenu));
                ops.put(good.getId() + "", JSON.toJSONString(good));

                //为了避免超卖问题，可以以SeckillGoodsCountList_id为key，以商品个数为数组的长度，以商品id为数组元素的内容（可以任意），
                //左边放入一个链表，抢单时抢一次就从右边取出一个数组元素
                String[] ids = new String[good.getStockCount()];
                Arrays.fill(ids, String.valueOf(good.getId()));
                redisTemplate.boundListOps("SeckillGoodsCountList_" + good.getId()).leftPushAll(ids);
                //1.4 以SeckillGoodsCount为大key，以商品id为小key，作一个对应商品的自增键（每次下单-1），以后下单扣的库存的实际数量，就是这里的自增键
                redisTemplate.boundHashOps("SeckillGoodsCount").put(String.valueOf(good.getId()),good.getStockCount());
            }
        }
    }
}
